package com.sali.handler;

import cn.hutool.json.JSONObject;
import com.sali.constants.CommonContent;
import com.sali.enums.ProtocolHandleTypeEnum;
import com.sali.model.BaseFieldRule;
import com.sali.model.FieldModel;
import com.sali.model.ProtocolModel;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.FileNotFoundException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @description: 对输入数据做字段模型转换
 * @author: sali
 * @date: 2024/7/16 20:51.
 * @version: 1.0
 */
@Slf4j
public class ProtocolModelHandle {

    @Getter
    private Map<String, ProtocolModel> protocolModelMap;

    private ProtocolModelLoad protocolModelLoad;

    @Builder(builderMethodName = "createBuilder")
    public ProtocolModelHandle(ProtocolModelLoad protocolModelLoad) {
        this.protocolModelLoad = protocolModelLoad;
    }

    /**
     * 模型初始化方法
     * ProtocolModelHandle的方法进行加载文件并解析文件内容
     *
     * @param filePath 文件名
     */
    public void init(String filePath) throws FileNotFoundException {
        if (StringUtils.isEmpty(filePath)) {
            throw new FileNotFoundException("ProtocolModelHandle.init() throw exception, filePath is empty.");
        }
        this.protocolModelMap = protocolModelLoad.fieldLoad(filePath);
    }

    public JSONObject handleModel(String protocol, Object content) {
        return this.handleModel(protocol, content, false);
    }

    /**
     * 根据原始消息进行模型转换处理
     * 1、对原始字段进行转换
     * 2、判断必须字段是否存在
     * 1、不存在返回null
     * 2、存在返回完整JSONObject
     */
    public JSONObject handleModel(String protocol, Object content, boolean openMailDateCheck) {
        if (StringUtils.isEmpty(protocol) || content == null) {
            return null;
        }
        if (protocolModelMap.containsKey(protocol)) {
            JSONObject jsonObject = new JSONObject();
            try {
                ProtocolModel protocolModel = getProtocolModel(protocol);
                List<BaseFieldRule> fieldRules = protocolModel.getBaseFieldRules();
                /**
                 * 处理待转换字段
                 */
                List<FieldModel> fieldModels = fieldRules.stream().map(new FieldRuleHandle(protocolModel, content)).collect(Collectors.toList());
                for (FieldModel fieldModel : fieldModels) {
                    String key = fieldModel.getField();
                    Object value = fieldModel.getValue();
                    if (fieldModel.isMust() && value == null) {
                        return null;
                    } else if (openMailDateCheck && "mail_date".equals(key) && value == null) {
                        //临时添加mail_date处理时间，当为null时先写入本地
                        return null;
                    } else if (!openMailDateCheck && "mail_date".equals(key) && value == null) {
                        ///临时添加mail_date处理时间，当为null时并且是邮件协议和不需要检查时使用系统时间
                        jsonObject.put(key, System.currentTimeMillis());
                    } else if (value == null) {
                        jsonObject.put(key, "null");
                    } else {
                        jsonObject.put(key, value);
                    }
                }
                /**
                 * 处理扩展字段
                 */
                ProtocolHandleTypeEnum handleType = protocolModel.getHandleType();
                if (ProtocolHandleTypeEnum.FILE_HANDLE_TYPE.equals(handleType) && protocol.startsWith(CommonContent.DATASOURCE_PREFIX)) {
                    //获取模型中使用到的原始字段
                    List<String> fields = fieldRules.stream().map(BaseFieldRule::getSrcFields).filter(strings -> strings != null && !strings.isEmpty()).flatMap(strings -> strings.stream()).collect(Collectors.toList());
                    JSONObject extendJson = new JSONObject();
                    JSONObject newJson = (JSONObject) content;
                    //获取报文中所有原始字段
                    Set<String> keySet = newJson.keySet();
                    //获取没有使用的字段加入扩展字段中
                    keySet.stream().filter(key -> !fields.contains(key)).forEach(key -> {
                        Object value = newJson.get(key);
                        extendJson.put(key, value);
                    });
                    if (!extendJson.isEmpty()) {
                        jsonObject.put("extend_column", extendJson.toString());
                    }
                }
            } catch (Exception e) {
                log.error("protocol model handle is error, message is{}, cause is", e.getMessage(), e);
            }
            return jsonObject;
        } else {
            return null;
        }
    }

    public ProtocolModel getProtocolModel(String protocol) {
        return protocolModelMap.getOrDefault(protocol, null);
    }
}